package org.lessnote.server.service;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.lboot.core.auth.AuthService;
import org.lboot.s3.client.S3Client;
import org.lboot.s3.params.FileUploadParams;
import org.lessnote.server.config.NoteConstant;
import org.lessnote.server.domain.DirFile;
import org.lessnote.server.domain.NoteDir;
import org.lessnote.server.params.NoteFileParams;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @author kindear
 * 笔记处理
 */
@Slf4j
@Service
@AllArgsConstructor
public class NoteCtl {
    S3Client s3Client;

    AuthService authService;

    private void upload(FileUploadParams params, String prefix) {
    }


    private List<NoteDir> buildSubDir(List<NoteDir> dirs, int idx, String[] paths){
        int len = paths.length;
        // 如果还没有到达最后一个
        if (idx < len){
            NoteDir noteDir = new NoteDir();
            StringBuilder sb = new StringBuilder();
            for(int k = 0; k <= idx; k++){
                sb.append(paths[k]);
                if (k <= idx - 1){
                    sb.append("/");
                }
            }
            noteDir.setFullPath(sb.toString());
            noteDir.setPath(paths[idx]);
            noteDir.setSubDirs(buildSubDir(idx+1, paths));
            // 传递构建
            boolean isMatch = false;
            for (NoteDir t:dirs){
                //log.info(t.toString());
                if (noteDir.getFullPath().equals(t.getFullPath())){
                    t.setSubDirs(buildSubDir(t.getSubDirs(), idx+1, paths));
                    isMatch = true;
                }
            }
            if (!isMatch){
                dirs.add(noteDir);
            }

        }
        return dirs;
    }

    private List<NoteDir> buildSubDir(int idx,String[] paths){
        int len = paths.length;
        List<NoteDir> dirs = new ArrayList<>();
        // 如果还没有到达最后一个
        if (idx < len){
            NoteDir noteDir = new NoteDir();
            StringBuilder sb = new StringBuilder();
            for(int k = 0; k <= idx; k++){
                sb.append(paths[k]);
                if (k <= idx - 1){
                    sb.append("/");
                }
            }
            noteDir.setFullPath(sb.toString());
            noteDir.setPath(paths[idx]);
            noteDir.setSubDirs(buildSubDir(idx+1, paths));
            dirs.add(noteDir);
            return dirs;
        }
        return new ArrayList<>();
    }

    @SneakyThrows
    public List<NoteDir> mkdir(String path){
        String uid = authService.getUid();
        // 定义索引 key
        String indexKey = uid + "/index.json";
        try {
            // 创建
            String[] paths = path.split("/");
            // 从S3获取对象
            S3Object s3Object = s3Client.getObject(NoteConstant.NOTE_BUCKET, indexKey);
            InputStream inputStream = s3Object.getObjectContent();
            String jsonStr = IoUtil.read(inputStream, StandardCharsets.UTF_8);
            List<NoteDir> dirs = JSONUtil.toList(jsonStr, NoteDir.class);
            buildSubDir(dirs,0, paths);
            // 对象转化为json字符串
            String dirJsonStr = JSONUtil.toJsonStr(dirs);
            s3Client.putObject(NoteConstant.NOTE_BUCKET, indexKey, IoUtil.toStream(dirJsonStr,StandardCharsets.UTF_8));
            return dirs;
        }catch (Exception e){
            String[] paths = path.split("/");
            // 不存在则新建
            List<NoteDir> dirs = buildSubDir(0, paths);
            // 对象转化为json字符串
            String jsonStr = JSONUtil.toJsonStr(dirs);
            s3Client.putObject(NoteConstant.NOTE_BUCKET, indexKey, IoUtil.toStream(jsonStr,StandardCharsets.UTF_8));
            return dirs;
        }
    }

    public List<NoteDir> getDirs(){
        String uid = authService.getUid();
        // 定义索引 key
        String indexKey = uid + "/index.json";
        // 从S3获取对象
        S3Object s3Object = s3Client.getObject(NoteConstant.NOTE_BUCKET, indexKey);
        InputStream inputStream = s3Object.getObjectContent();
        String jsonStr = IoUtil.read(inputStream, StandardCharsets.UTF_8);
        List<NoteDir> dirs = JSONUtil.toList(jsonStr, NoteDir.class);
        return dirs;
    }



    public List<DirFile> uploadFile(NoteFileParams params) throws IOException {
        // 截取
        DirFile dirFile = new DirFile();
        String fullPath = params.getFullPath();
        dirFile.setFullPath(fullPath);
        String fileName = StrUtil.subAfter(fullPath,"/",true);
        log.info("文件名称:{}", fileName);
        dirFile.setName(fileName);
        String dirPath = StrUtil.subBefore(fullPath, "/", true);
        log.info("目录路径:{}", dirPath);
        // 直接建一遍目录
        mkdir(dirPath);
        // 判断
        String uid = authService.getUid();
        // 定义索引 key
        String filesIndexKey = uid + "/" + dirPath + "/files-index.json";
        log.info(filesIndexKey);
        // 判断文件是否
        try {
            // 从S3获取对象
            S3Object s3Object = s3Client.getObject(NoteConstant.NOTE_BUCKET, filesIndexKey);

            InputStream inputStream = s3Object.getObjectContent();
            String jsonStr = IoUtil.read(inputStream, StandardCharsets.UTF_8);
            List<DirFile> files = JSONUtil.toList(jsonStr, DirFile.class);
            // 构建文件相关信息
            MultipartFile file = params.getFile();
            String md5 = SecureUtil.md5(file.getInputStream());
            boolean hasMatch = false;
            List<DirFile> newDirFiles = new ArrayList<>();
            for (DirFile ele:files){
                if (ele.getName().equals(dirFile.getName())){
                    hasMatch = true;
                    // 如果MD5 没有变化 --> 不做操作
                    if (ele.getMd5().equals(md5)){
                        log.info("文件:{}没有变化", fileName);
                        newDirFiles.add(ele);
                    }else {
                        // 获取最新名称
                        String latest = ele.getLatest();
                        // 截取版本
                        List<String> versions = ele.getVersions();
                        int versionCount = versions.size();
                        String fileKey = "@" + (versionCount+1) + "-" + fileName;
                        ele.setMd5(md5);
                        ele.setLatest(fileKey);
                        versions.add(fileKey);
                        ele.setVersions(versions);
                        ele.setSize(file.getSize());
                        // 上传文件
                        String objectName = uid +"/" + dirPath + "/" + fileKey;
                        log.info("对象名称:{}", objectName);
                        // 上传文件
                        s3Client.putObject(NoteConstant.NOTE_BUCKET, objectName, file);
                        // 写入新纪录
                        newDirFiles.add(ele);
                    }
                }else {
                    newDirFiles.add(ele);
                }
            }
            // 没有匹配
            if (!hasMatch){
                // 构建文件名称
                String fileKey = "@1-" + fileName;
                List<String> versions = new ArrayList<>();
                versions.add(fileKey);
                dirFile.setVersions(versions);
                dirFile.setLatest(fileKey);
                dirFile.setMd5(SecureUtil.md5(file.getInputStream()));
                dirFile.setSize(file.getSize());
                // 标签为空
                dirFile.setTags(new ArrayList<>());
                String objectName = uid +"/" + dirPath + "/" + fileKey;
                log.info("对象名称:{}", objectName);
                // 上传文件
                s3Client.putObject(NoteConstant.NOTE_BUCKET, objectName, file);
                newDirFiles.add(dirFile);
            }
            // 更新文件索引
            String filesJson = JSONUtil.toJsonStr(newDirFiles);
            s3Client.putObject(NoteConstant.NOTE_BUCKET, filesIndexKey, IoUtil.toStream(filesJson,StandardCharsets.UTF_8));
            return newDirFiles;
        }catch (Exception ignored){
            List<DirFile> files = new ArrayList<>();
            MultipartFile file = params.getFile();
            // 构建文件名称
            String fileKey = "@1-" + fileName;
            List<String> versions = new ArrayList<>();
            versions.add(fileKey);
            dirFile.setVersions(versions);
            dirFile.setLatest(fileKey);
            dirFile.setMd5(SecureUtil.md5(file.getInputStream()));
            dirFile.setSize(file.getSize());
            // 标签为空
            dirFile.setTags(new ArrayList<>());
            String objectName = uid +"/" + dirPath + "/" + fileKey;
            log.info("对象名称:{}", objectName);
            // 上传文件
            s3Client.putObject(NoteConstant.NOTE_BUCKET, objectName, file);
            files.add(dirFile);
            // 更新文件索引
            String jsonStr = JSONUtil.toJsonStr(files);

            s3Client.putObject(NoteConstant.NOTE_BUCKET, filesIndexKey, IoUtil.toStream(jsonStr,StandardCharsets.UTF_8));
            return files;
        }
    }


    public List<DirFile> listFiles(String dirPath){
        String uid = authService.getUid();
        // 定义索引 key
        String filesIndexKey = uid + "/" + dirPath + "/files-index.json";
        try{
            // 从S3获取对象
            S3Object s3Object = s3Client.getObject(NoteConstant.NOTE_BUCKET, filesIndexKey);

            InputStream inputStream = s3Object.getObjectContent();
            String jsonStr = IoUtil.read(inputStream, StandardCharsets.UTF_8);
            List<DirFile> files = JSONUtil.toList(jsonStr, DirFile.class);
            return files;
        }catch (Exception e){
            return new ArrayList<>();
        }
    }
}
